package lock;

public class SynchronizedTest {

	public static void main(String[] args){

//		objectLock();

		objectLock2();

//		classLock();

//		hybridInvoke();

//		syncException();
	}

	private static synchronized void syncException() {
		System.out.println("begin");
		System.out.println(3/0);
		System.out.println("end");
	}

	/**
	 * 结论: 用的不同的锁,所以不互斥
	 */
	private static void hybridInvoke() {
		SynchronizedTest test = new SynchronizedTest();
		new Thread(() -> {
			//用的对象锁
			test.method1();
		}, "thread-1").start();
		new Thread(() -> {
			// 静态方法用的类锁 下面2个方法等同
			test.staticMethod2();
//			staticMethod2();
		}, "thread-2").start();

	}

	/**
	 * 类锁只有一个,所以互斥
	 */
	private static void classLock() {
		new Thread(() -> {
			staticMethod1();
		}, "thread-1").start();
		new Thread(() -> {
			staticMethod2();
		}, "thread-2").start();

	}

	/**
	 * Java中每个对象都有一个锁，并且是唯一的。假设分配的一个对象空间，
	 * 里面有多个方法，相当于空间里面有多个小房间，如果我们把所有的小房间都加锁，
	 * 因为这个对象只有一把钥匙，因此同一时间只能有一个人打开一个小房间，
	 * 然后用完了还回去，再由JVM 去分配下一个获得钥匙的人。
	 * 结论:互斥
	 *
	 * 但是不同对象就没问题
	 */
	private static void objectLock() {
		SynchronizedTest test = new SynchronizedTest();
		SynchronizedTest test2 = new SynchronizedTest();
		new Thread(() -> {
			test.method1();
		}, "thread-1").start();
		new Thread(() -> {
			test.method2();
		}, "thread-2").start();
	}
	private static void objectLock2() {
		SynchronizedTest test = new SynchronizedTest();
		SynchronizedTest test2 = new SynchronizedTest();
		new Thread(() -> {
			test.method1();
		}, "thread-1").start();
		new Thread(() -> {
			test2.method2();
		}, "thread-2").start();
	}


	public void run1(){
		method1();
	}
	public void run2(){
		method2();
	}

	public static SynchronizedTest staticIn = new SynchronizedTest();   //静态对象
	
     public synchronized void method1(){                                   //非静态方法1
    	 for(int i = 0;i < 10;i++){  
    		 System.out.println("method1 is running!");
    		 try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	 }
     }
     public synchronized void method2(){                                   //非静态方法2
    	 for( int i = 0; i < 10 ; i++){
    		 System.out.println("method2 is running!");
    		 try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	 }
     }
    public synchronized static void staticMethod1(){                     //静态方法1
    	for( int i = 0; i < 10 ; i++){
   		 System.out.println("static method1 is running!");
   		 try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
   	 }
    }
    public synchronized static void staticMethod2(){                      //静态方法2
    	for( int i = 0; i < 10 ; i++){
   		 System.out.println("static method2 is running!");
   		 try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
   	 }
    }
}